#include "fileOperationsHeader.h"
char *addFile(char *path,char *fileName,char *data)
{
	if(mh==NULL)
		return ERR_VFS_ADDFILE_07;
	if(validFilenameCheck(fileName)==FALSE)
		return ERR_VFS_ADDFILE_02;
	int z=strlen(path);
	if(z!=1 && path[z-1]=='/')
		path[z-1]='\0';
	char *pathTokens = NULL;
	char *tempPath=(char*)malloc(sizeof(char)*(strlen(path)+1));
	sprintf(tempPath,"%s",path);
	nAryNode *temp=nAryRoot;
	int found=0;
	pathTokens = strtok( tempPath, "/" );
	while(pathTokens!=NULL)
	{
		found=0;
		if(temp==nAryRoot)
		{
			if(temp->child!=NULL)
				temp=temp->child;
			else
				return ERR_VFS_ADDFILE_01;
		}
		else
		{
			while(temp->sibling!=NULL)
			{
				if(strcmp(temp->name,pathTokens)!=0)
					temp=temp->sibling;
				else
				{
					found=1;
					break;
				}
			}
			if(strcmp(temp->name,pathTokens)==0)
				found=1;
			if(!found)
				return ERR_VFS_ADDFILE_01;
			pathTokens = strtok( NULL, "/" );
			if(pathTokens!=NULL && temp->child==NULL)
				return ERR_VFS_ADDFILE_01;
			if(temp->child!=NULL)
				temp=temp->child;
		}
	}
	char *completePath=(char*)malloc(sizeof(char)*(strlen(path)+1+strlen(fileName)+1));
	if(strcmp(path,"/")!=0)
		sprintf(completePath,"%s/%s",path,fileName);
	else
		sprintf(completePath,"%s%s",path,fileName);
	descriptors *d=(descriptors*)malloc(sizeof(descriptors));
	d=(descriptors*)searchBST(completePath);
	if(d!=NULL)
		return ERR_VFS_ADDFILE_03;
	int iterDescriptors=0;
	int maxFileDescriptors=mh->maxDescriptors;
	int currentFileDescriptors=mh->countOfFileDescriptors;
	if(currentFileDescriptors==maxFileDescriptors)
		return ERR_VFS_ADDFILE_04;
	int noOfBlocks=maxFileDescriptors/2;
	while(iterDescriptors<maxFileDescriptors)
	{
		if(h->desc[iterDescriptors].type!='f' && h->desc[iterDescriptors].type!='d')
			break;
		iterDescriptors++;
	}
	int iterFreeBlock=0;
	while(iterFreeBlock<noOfBlocks)
	{
		if(h->freeList[iterFreeBlock]=='0')
			break;
		iterFreeBlock++;
	}
	FILE *fpData=fopen(data,"r");
	if(fpData==NULL)
		return ERR_VFS_ADDFILE_05;
	FILE *fp=fopen(mh->fileSystemLabel,"r+b");
	if(fp==NULL)
		return ERR_VFS_ADDFILE_05;
	fseek(fpData,0,SEEK_END);
	int size=ftell(fpData);
	if(size>maxBlockSize)
		return ERR_VFS_ADDFILE_06;
	descriptors *new=(descriptors*)malloc(sizeof(descriptors));
	sprintf(new->fileName,"%s",fileName);
	sprintf(new->location,"%s",path);
	new->type='f';
	new->blockNumber=iterFreeBlock;
	new->size=size;
	h->desc[iterDescriptors]=*new;
	h->freeList[iterFreeBlock]='1';
	int address=(int)arr[iterFreeBlock];
	fseek(fp,address,SEEK_SET);
	rewind(fpData);
	char *str=(char*)malloc(sizeof(char)*size);
	fread(str,size,1,fpData);
	fwrite(str,size,1,fp);
	mh->countOfFileDescriptors=mh->countOfFileDescriptors+1;
	fclose(fpData);
	fclose(fp);
	char *absolutePathForBST=NULL;
	absolutePathForBST=(char*)malloc(sizeof(char)*(strlen(h->desc[iterDescriptors].location)+1+strlen(h->desc[iterDescriptors].fileName)+1));
	if(strcmp(h->desc[iterDescriptors].location,"/")!=0)
		sprintf(absolutePathForBST,"%s/%s",h->desc[iterDescriptors].location,h->desc[iterDescriptors].fileName);
	else
		sprintf(absolutePathForBST,"%s%s",h->desc[iterDescriptors].location,h->desc[iterDescriptors].fileName);
	int bstRet=insertBST(absolutePathForBST,h->desc[iterDescriptors].blockNumber);
	if(bstRet!=0)
		return "FAILURE <while inserting into BST>";
	//displayBST(root);
	int nAryRet=createnAryTree(maxFileDescriptors,h->desc);
	if(nAryRet!=0)
		return "FAILURE <while creating nAryTree>";
	node *hashTableInsertionReturn=insert_ht(hashtable,h->desc[iterDescriptors].fileName,h->desc[iterDescriptors].blockNumber,h->desc[iterDescriptors].location);
	if(hashTableInsertionReturn==NULL)
		return "FAILURE <while entering into hashTable>";
	return "SUCCESS";
}
int validFilenameCheck(char *fileName)
{
    int i = 0 ;
    for(i=0;fileName[i] != '\0';i++)
    {
		if(fileName[i] == '/')
			return FALSE;
	}
	return TRUE;
}
